/*
 * Copyright (C) 2005 - 2013 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008 - 2013 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2010 - 2013 ProjectSkyfire <http://www.projectskyfire.org/>
 *
 * Copyright (C) 2011 - 2013 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef _ITEMPROTOTYPE_H
#define _ITEMPROTOTYPE_H

#include "Common.h"
#include "SharedDefines.h"
#include "DBCStructure.h"

enum ItemModType
{
    ITEM_MOD_MANA = 0, ITEM_MOD_HEALTH = 1, ITEM_MOD_AGILITY = 3, ITEM_MOD_STRENGTH = 4, ITEM_MOD_INTELLECT = 5, ITEM_MOD_SPIRIT = 6, ITEM_MOD_STAMINA = 7, ITEM_MOD_DEFENSE_SKILL_RATING = 12, ITEM_MOD_DODGE_RATING = 13, ITEM_MOD_PARRY_RATING = 14, ITEM_MOD_BLOCK_RATING = 15, ITEM_MOD_HIT_MELEE_RATING = 16, ITEM_MOD_HIT_RANGED_RATING = 17, ITEM_MOD_HIT_SPELL_RATING = 18, ITEM_MOD_CRIT_MELEE_RATING = 19, ITEM_MOD_CRIT_RANGED_RATING = 20, ITEM_MOD_CRIT_SPELL_RATING = 21, ITEM_MOD_HIT_TAKEN_MELEE_RATING = 22, ITEM_MOD_HIT_TAKEN_RANGED_RATING = 23, ITEM_MOD_HIT_TAKEN_SPELL_RATING = 24, ITEM_MOD_CRIT_TAKEN_MELEE_RATING = 25, ITEM_MOD_CRIT_TAKEN_RANGED_RATING = 26, ITEM_MOD_CRIT_TAKEN_SPELL_RATING = 27, ITEM_MOD_HASTE_MELEE_RATING = 28, ITEM_MOD_HASTE_RANGED_RATING = 29, ITEM_MOD_HASTE_SPELL_RATING = 30, ITEM_MOD_HIT_RATING = 31, ITEM_MOD_CRIT_RATING = 32, ITEM_MOD_HIT_TAKEN_RATING = 33, ITEM_MOD_CRIT_TAKEN_RATING = 34, ITEM_MOD_RESILIENCE_RATING = 35, ITEM_MOD_HASTE_RATING = 36, ITEM_MOD_EXPERTISE_RATING = 37, ITEM_MOD_ATTACK_POWER = 38, ITEM_MOD_RANGED_ATTACK_POWER = 39,
    //ITEM_MOD_FERAL_ATTACK_POWER       = 40, not in 3.3
    ITEM_MOD_SPELL_HEALING_DONE = 41,          // deprecated
    ITEM_MOD_SPELL_DAMAGE_DONE = 42,          // deprecated
    ITEM_MOD_MANA_REGENERATION = 43, ITEM_MOD_ARMOR_PENETRATION_RATING = 44, ITEM_MOD_SPELL_POWER = 45, ITEM_MOD_HEALTH_REGEN = 46, ITEM_MOD_SPELL_PENETRATION = 47, ITEM_MOD_BLOCK_VALUE = 48, ITEM_MOD_MASTERY_RATING = 49, ITEM_MOD_EXTRA_ARMOR = 50, ITEM_MOD_FIRE_RESISTANCE = 51, ITEM_MOD_FROST_RESISTANCE = 52, ITEM_MOD_HOLY_RESISTANCE = 53, ITEM_MOD_SHADOW_RESISTANCE = 54, ITEM_MOD_NATURE_RESISTANCE = 55, ITEM_MOD_ARCANE_RESISTANCE = 56
};

#define MAX_ITEM_MOD                    57

enum ItemSpelltriggerType
{
    ITEM_SPELLTRIGGER_ON_USE = 0,          // use after equip cooldown
    ITEM_SPELLTRIGGER_ON_EQUIP = 1, ITEM_SPELLTRIGGER_CHANCE_ON_HIT = 2, ITEM_SPELLTRIGGER_SOULSTONE = 4,
    /*
     * ItemSpelltriggerType 5 might have changed on 2.4.3/3.0.3: Such auras
     * will be applied on item pickup and removed on item loss - maybe on the
     * other hand the item is destroyed if the aura is removed ("removed on
     * death" of spell 57348 makes me think so)
     */
    ITEM_SPELLTRIGGER_ON_NO_DELAY_USE = 5,          // no equip cooldown
    ITEM_SPELLTRIGGER_LEARN_SPELL_ID = 6
// used in item_template.spell_2 with spell_id with SPELL_GENERIC_LEARN in spell_1
};

#define MAX_ITEM_SPELLTRIGGER           7

enum ItemBondingType
{
    NO_BIND = 0, BIND_WHEN_PICKED_UP = 1, BIND_WHEN_EQUIPED = 2, BIND_WHEN_USE = 3, BIND_QUEST_ITEM = 4, BIND_QUEST_ITEM1 = 5
// not used in game
};

#define MAX_BIND_TYPE                             6

/* TODO
 // need to know cases when using item is not allowed in shapeshift
 ITEM_PROTO_FLAG_USABLE_WHEN_SHAPESHIFTED    = 0x00800000, // Item can be used in shapeshift forms
 */

enum ItemProtoFlags
{
    ITEM_PROTO_FLAG_UNK1 = 0x00000001,          // ?
    ITEM_PROTO_FLAG_CONJURED = 0x00000002,          // Conjured item
    ITEM_PROTO_FLAG_OPENABLE = 0x00000004,          // Item can be right clicked to open for loot
    ITEM_PROTO_FLAG_HEROIC = 0x00000008,          // Makes green "Heroic" text appear on item
    ITEM_PROTO_FLAG_DEPRECATED = 0x00000010,          // Cannot equip or use
    ITEM_PROTO_FLAG_INDESTRUCTIBLE = 0x00000020,          // Item can not be destroyed, except by using spell (item can be reagent for spell)
    ITEM_PROTO_FLAG_UNK2 = 0x00000040,          // ?
    ITEM_PROTO_FLAG_NO_EQUIP_COOLDOWN = 0x00000080,          // No default 30 seconds cooldown when equipped
    ITEM_PROTO_FLAG_UNK3 = 0x00000100,          // ?
    ITEM_PROTO_FLAG_WRAPPER = 0x00000200,          // Item can wrap other items
    ITEM_PROTO_FLAG_UNK4 = 0x00000400,          // ?
    ITEM_PROTO_FLAG_PARTY_LOOT = 0x00000800,          // Looting this item does not remove it from available loot
    ITEM_PROTO_FLAG_REFUNDABLE = 0x00001000,          // Item can be returned to vendor for its original cost (extended cost)
    ITEM_PROTO_FLAG_CHARTER = 0x00002000,          // Item is guild or arena charter
    ITEM_PROTO_FLAG_UNK5 = 0x00004000,          // Only readable items have this (but not all)
    ITEM_PROTO_FLAG_UNK6 = 0x00008000,          // ?
    ITEM_PROTO_FLAG_UNK7 = 0x00010000,          // ?
    ITEM_PROTO_FLAG_UNK8 = 0x00020000,          // ?
    ITEM_PROTO_FLAG_PROSPECTABLE = 0x00040000,          // Item can be prospected
    ITEM_PROTO_FLAG_UNIQUE_EQUIPPED = 0x00080000,          // You can only equip one of these
    ITEM_PROTO_FLAG_UNK9 = 0x00100000,          // ?
    ITEM_PROTO_FLAG_USEABLE_IN_ARENA = 0x00200000,          // Item can be used during arena match
    ITEM_PROTO_FLAG_THROWABLE = 0x00400000,          // Some Thrown weapons have it (and only Thrown) but not all
    ITEM_PROTO_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000,          // Item can be used in shapeshift forms
    ITEM_PROTO_FLAG_UNK10 = 0x01000000,          // ?
    ITEM_PROTO_FLAG_SMART_LOOT = 0x02000000,          // Profession recipes: can only be looted if you meet requirements and don't already know it
    ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA = 0x04000000,          // Item cannot be used in arena
    ITEM_PROTO_FLAG_BIND_TO_ACCOUNT = 0x08000000,          // Item binds to account and can be sent only to your own characters
    ITEM_PROTO_FLAG_TRIGGERED_CAST = 0x10000000,          // Spell is cast with triggered flag
    ITEM_PROTO_FLAG_MILLABLE = 0x20000000,          // Item can be milled
    ITEM_PROTO_FLAG_UNK11 = 0x40000000,          // ?
    ITEM_PROTO_FLAG_UNK12 = 0x80000000
// ?
};

/* TODO
 */

enum ItemFieldFlags
{
    ITEM_FLAG_SOULBOUND = 0x00000001,          // Item is soulbound and cannot be traded <<--
    ITEM_FLAG_UNK1 = 0x00000002,          // ?
    ITEM_FLAG_UNLOCKED = 0x00000004,          // Item had lock but can be opened now
    ITEM_FLAG_WRAPPED = 0x00000008,          // Item is wrapped and contains another item
    ITEM_FLAG_UNK2 = 0x00000010,          // ?
    ITEM_FLAG_UNK3 = 0x00000020,          // ?
    ITEM_FLAG_UNK4 = 0x00000040,          // ?
    ITEM_FLAG_UNK5 = 0x00000080,          // ?
    ITEM_FLAG_BOP_TRADEABLE = 0x00000100,          // Allows trading soulbound items
    ITEM_FLAG_READABLE = 0x00000200,          // Opens text page when right clicked
    ITEM_FLAG_UNK6 = 0x00000400,          // ?
    ITEM_FLAG_UNK7 = 0x00000800,          // ?
    ITEM_FLAG_REFUNDABLE = 0x00001000,          // Item can be returned to vendor for its original cost (extended cost)
    ITEM_FLAG_UNK8 = 0x00002000,          // ?
    ITEM_FLAG_UNK9 = 0x00004000,          // ?
    ITEM_FLAG_UNK10 = 0x00008000,          // ?
    ITEM_FLAG_UNK11 = 0x00010000,          // ?
    ITEM_FLAG_UNK12 = 0x00020000,          // ?
    ITEM_FLAG_UNK13 = 0x00040000,          // ?
    ITEM_FLAG_UNK14 = 0x00080000,          // ?
    ITEM_FLAG_UNK15 = 0x00100000,          // ?
    ITEM_FLAG_UNK16 = 0x00200000,          // ?
    ITEM_FLAG_UNK17 = 0x00400000,          // ?
    ITEM_FLAG_UNK18 = 0x00800000,          // ?
    ITEM_FLAG_UNK19 = 0x01000000,          // ?
    ITEM_FLAG_UNK20 = 0x02000000,          // ?
    ITEM_FLAG_UNK21 = 0x04000000,          // ?
    ITEM_FLAG_UNK22 = 0x08000000,          // ?
    ITEM_FLAG_UNK23 = 0x10000000,          // ?
    ITEM_FLAG_UNK24 = 0x20000000,          // ?
    ITEM_FLAG_UNK25 = 0x40000000,          // ?
    ITEM_FLAG_UNK26 = 0x80000000,          // ?

    ITEM_FLAG_MAIL_TEXT_MASK = ITEM_FLAG_READABLE | ITEM_FLAG_UNK13 | ITEM_FLAG_UNK14,
};

enum ItemFlagsExtra
{
    ITEM_FLAGS_EXTRA_HORDE_ONLY = 0x00000001, ITEM_FLAGS_EXTRA_ALLIANCE_ONLY = 0x00000002, ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD = 0x00000004,          // when item uses extended cost, gold is also required
    ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED = 0x00000100, ITEM_FLAGS_EXTRA_CASTER_WEAPON = 0x00000200,
// uses caster specific dbc file for DPS calculations
};

enum BAG_FAMILY_MASK
{
    BAG_FAMILY_MASK_NONE = 0x00000000, BAG_FAMILY_MASK_ARROWS = 0x00000001, BAG_FAMILY_MASK_BULLETS = 0x00000002, BAG_FAMILY_MASK_SOUL_SHARDS = 0x00000004, BAG_FAMILY_MASK_LEATHERWORKING_SUPP = 0x00000008, BAG_FAMILY_MASK_INSCRIPTION_SUPP = 0x00000010, BAG_FAMILY_MASK_HERBS = 0x00000020, BAG_FAMILY_MASK_ENCHANTING_SUPP = 0x00000040, BAG_FAMILY_MASK_ENGINEERING_SUPP = 0x00000080, BAG_FAMILY_MASK_KEYS = 0x00000100, BAG_FAMILY_MASK_GEMS = 0x00000200, BAG_FAMILY_MASK_MINING_SUPP = 0x00000400, BAG_FAMILY_MASK_SOULBOUND_EQUIPMENT = 0x00000800, BAG_FAMILY_MASK_VANITY_PETS = 0x00001000, BAG_FAMILY_MASK_CURRENCY_TOKENS = 0x00002000, BAG_FAMILY_MASK_QUEST_ITEMS = 0x00004000, BAG_FAMILY_MASK_FISHING = 0x00008000
};

enum SocketColor
{
    SOCKET_COLOR_META = 1, SOCKET_COLOR_RED = 2, SOCKET_COLOR_YELLOW = 4, SOCKET_COLOR_BLUE = 8, SOCKET_COLOR_HYDRAULIC = 16, SOCKET_COLOR_COGWHEEL = 32,
};

#define SOCKET_COLOR_ALL (SOCKET_COLOR_META | SOCKET_COLOR_RED | SOCKET_COLOR_YELLOW | SOCKET_COLOR_BLUE | SOCKET_COLOR_HYDRAULIC | SOCKET_COLOR_COGWHEEL)

enum InventoryType
{
    INVTYPE_NON_EQUIP = 0, INVTYPE_HEAD = 1, INVTYPE_NECK = 2, INVTYPE_SHOULDERS = 3, INVTYPE_BODY = 4, INVTYPE_CHEST = 5, INVTYPE_WAIST = 6, INVTYPE_LEGS = 7, INVTYPE_FEET = 8, INVTYPE_WRISTS = 9, INVTYPE_HANDS = 10, INVTYPE_FINGER = 11, INVTYPE_TRINKET = 12, INVTYPE_WEAPON = 13, INVTYPE_SHIELD = 14, INVTYPE_RANGED = 15, INVTYPE_CLOAK = 16, INVTYPE_2HWEAPON = 17, INVTYPE_BAG = 18, INVTYPE_TABARD = 19, INVTYPE_ROBE = 20, INVTYPE_WEAPONMAINHAND = 21, INVTYPE_WEAPONOFFHAND = 22, INVTYPE_HOLDABLE = 23, INVTYPE_AMMO = 24, INVTYPE_THROWN = 25, INVTYPE_RANGEDRIGHT = 26, INVTYPE_QUIVER = 27, INVTYPE_RELIC = 28
};

#define MAX_INVTYPE                               29

enum ItemClass
{
    ITEM_CLASS_CONSUMABLE = 0, ITEM_CLASS_CONTAINER = 1, ITEM_CLASS_WEAPON = 2, ITEM_CLASS_GEM = 3, ITEM_CLASS_ARMOR = 4, ITEM_CLASS_REAGENT = 5, ITEM_CLASS_PROJECTILE = 6, ITEM_CLASS_TRADE_GOODS = 7, ITEM_CLASS_GENERIC = 8, ITEM_CLASS_RECIPE = 9, ITEM_CLASS_MONEY = 10, ITEM_CLASS_QUIVER = 11, ITEM_CLASS_QUEST = 12, ITEM_CLASS_KEY = 13, ITEM_CLASS_PERMANENT = 14, ITEM_CLASS_MISC = 15, ITEM_CLASS_GLYPH = 16
};

#define MAX_ITEM_CLASS                            17

enum ItemSubclassConsumable
{
    ITEM_SUBCLASS_CONSUMABLE = 0, ITEM_SUBCLASS_POTION = 1, ITEM_SUBCLASS_ELIXIR = 2, ITEM_SUBCLASS_FLASK = 3, ITEM_SUBCLASS_SCROLL = 4, ITEM_SUBCLASS_FOOD = 5, ITEM_SUBCLASS_ITEM_ENHANCEMENT = 6, ITEM_SUBCLASS_BANDAGE = 7, ITEM_SUBCLASS_CONSUMABLE_OTHER = 8
};

#define MAX_ITEM_SUBCLASS_CONSUMABLE              9

enum ItemSubclassContainer
{
    ITEM_SUBCLASS_CONTAINER = 0, ITEM_SUBCLASS_SOUL_CONTAINER = 1, ITEM_SUBCLASS_HERB_CONTAINER = 2, ITEM_SUBCLASS_ENCHANTING_CONTAINER = 3, ITEM_SUBCLASS_ENGINEERING_CONTAINER = 4, ITEM_SUBCLASS_GEM_CONTAINER = 5, ITEM_SUBCLASS_MINING_CONTAINER = 6, ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7, ITEM_SUBCLASS_INSCRIPTION_CONTAINER = 8, ITEM_SUBCLASS_FISHING_CONTAINER = 9
};

#define MAX_ITEM_SUBCLASS_CONTAINER               10

enum ItemSubclassWeapon
{
    ITEM_SUBCLASS_WEAPON_AXE = 0, ITEM_SUBCLASS_WEAPON_AXE2 = 1, ITEM_SUBCLASS_WEAPON_BOW = 2, ITEM_SUBCLASS_WEAPON_GUN = 3, ITEM_SUBCLASS_WEAPON_MACE = 4, ITEM_SUBCLASS_WEAPON_MACE2 = 5, ITEM_SUBCLASS_WEAPON_POLEARM = 6, ITEM_SUBCLASS_WEAPON_SWORD = 7, ITEM_SUBCLASS_WEAPON_SWORD2 = 8, ITEM_SUBCLASS_WEAPON_obsolete = 9, ITEM_SUBCLASS_WEAPON_STAFF = 10, ITEM_SUBCLASS_WEAPON_EXOTIC = 11, ITEM_SUBCLASS_WEAPON_EXOTIC2 = 12, ITEM_SUBCLASS_WEAPON_FIST = 13, ITEM_SUBCLASS_WEAPON_MISC = 14, ITEM_SUBCLASS_WEAPON_DAGGER = 15, ITEM_SUBCLASS_WEAPON_THROWN = 16, ITEM_SUBCLASS_WEAPON_SPEAR = 17, ITEM_SUBCLASS_WEAPON_CROSSBOW = 18, ITEM_SUBCLASS_WEAPON_WAND = 19, ITEM_SUBCLASS_WEAPON_FISHING_POLE = 20
};

#define ITEM_SUBCLASS_MASK_WEAPON_RANGED (\
    (1 << ITEM_SUBCLASS_WEAPON_BOW) | (1 << ITEM_SUBCLASS_WEAPON_GUN) |\
    (1 << ITEM_SUBCLASS_WEAPON_CROSSBOW) | (1 << ITEM_SUBCLASS_WEAPON_THROWN))

#define MAX_ITEM_SUBCLASS_WEAPON                  21

enum ItemSubclassGem
{
    ITEM_SUBCLASS_GEM_RED = 0, ITEM_SUBCLASS_GEM_BLUE = 1, ITEM_SUBCLASS_GEM_YELLOW = 2, ITEM_SUBCLASS_GEM_PURPLE = 3, ITEM_SUBCLASS_GEM_GREEN = 4, ITEM_SUBCLASS_GEM_ORANGE = 5, ITEM_SUBCLASS_GEM_META = 6, ITEM_SUBCLASS_GEM_SIMPLE = 7, ITEM_SUBCLASS_GEM_PRISMATIC = 8, ITEM_SUBCLASS_GEM_HYDRAULIC = 9, ITEM_SUBCLASS_GEM_COGWHEEL = 10
};

#define MAX_ITEM_SUBCLASS_GEM                     11

enum ItemSubclassArmor
{
    ITEM_SUBCLASS_ARMOR_MISC = 0, ITEM_SUBCLASS_ARMOR_CLOTH = 1, ITEM_SUBCLASS_ARMOR_LEATHER = 2, ITEM_SUBCLASS_ARMOR_MAIL = 3, ITEM_SUBCLASS_ARMOR_PLATE = 4, ITEM_SUBCLASS_ARMOR_BUCKLER = 5, ITEM_SUBCLASS_ARMOR_SHIELD = 6,
    //ITEM_SUBCLASS_ARMOR_LIBRAM                  = 7,
    //ITEM_SUBCLASS_ARMOR_IDOL                    = 8,
    //ITEM_SUBCLASS_ARMOR_TOTEM                   = 9,
    //ITEM_SUBCLASS_ARMOR_SIGIL                   = 10,
    ITEM_SUBCLASS_ARMOR_RELIC = 11
};

#define MAX_ITEM_SUBCLASS_ARMOR                   12

enum ItemSubclassReagent
{
    ITEM_SUBCLASS_REAGENT = 0
};

#define MAX_ITEM_SUBCLASS_REAGENT                 1

enum ItemSubclassProjectile
{
    ITEM_SUBCLASS_WAND = 0,          // ABS
    ITEM_SUBCLASS_BOLT = 1,          // ABS
    ITEM_SUBCLASS_ARROW = 2, ITEM_SUBCLASS_BULLET = 3, ITEM_SUBCLASS_THROWN = 4
// ABS
};

#define MAX_ITEM_SUBCLASS_PROJECTILE              5

enum ItemSubclassTradeGoods
{
    ITEM_SUBCLASS_TRADE_GOODS = 0, ITEM_SUBCLASS_PARTS = 1, ITEM_SUBCLASS_EXPLOSIVES = 2, ITEM_SUBCLASS_DEVICES = 3, ITEM_SUBCLASS_JEWELCRAFTING = 4, ITEM_SUBCLASS_CLOTH = 5, ITEM_SUBCLASS_LEATHER = 6, ITEM_SUBCLASS_METAL_STONE = 7, ITEM_SUBCLASS_MEAT = 8, ITEM_SUBCLASS_HERB = 9, ITEM_SUBCLASS_ELEMENTAL = 10, ITEM_SUBCLASS_TRADE_GOODS_OTHER = 11, ITEM_SUBCLASS_ENCHANTING = 12, ITEM_SUBCLASS_MATERIAL = 13, ITEM_SUBCLASS_ARMOR_ENCHANTMENT = 14, ITEM_SUBCLASS_WEAPON_ENCHANTMENT = 15
};

#define MAX_ITEM_SUBCLASS_TRADE_GOODS             16

enum ItemSubclassGeneric
{
    ITEM_SUBCLASS_GENERIC = 0
};

#define MAX_ITEM_SUBCLASS_GENERIC                 1

enum ItemSubclassRecipe
{
    ITEM_SUBCLASS_BOOK = 0, ITEM_SUBCLASS_LEATHERWORKING_PATTERN = 1, ITEM_SUBCLASS_TAILORING_PATTERN = 2, ITEM_SUBCLASS_ENGINEERING_SCHEMATIC = 3, ITEM_SUBCLASS_BLACKSMITHING = 4, ITEM_SUBCLASS_COOKING_RECIPE = 5, ITEM_SUBCLASS_ALCHEMY_RECIPE = 6, ITEM_SUBCLASS_FIRST_AID_MANUAL = 7, ITEM_SUBCLASS_ENCHANTING_FORMULA = 8, ITEM_SUBCLASS_FISHING_MANUAL = 9, ITEM_SUBCLASS_JEWELCRAFTING_RECIPE = 10, ITEM_SUBCLASS_INSCRIPTION_TECHNIQUE = 11
};

#define MAX_ITEM_SUBCLASS_RECIPE                  12

enum ItemSubclassMoney
{
    ITEM_SUBCLASS_MONEY = 0
};

#define MAX_ITEM_SUBCLASS_MONEY                   1

enum ItemSubclassQuiver
{
    ITEM_SUBCLASS_QUIVER0 = 0,          // ABS
    ITEM_SUBCLASS_QUIVER1 = 1,          // ABS
    ITEM_SUBCLASS_QUIVER = 2, ITEM_SUBCLASS_AMMO_POUCH = 3
};

#define MAX_ITEM_SUBCLASS_QUIVER                  4

enum ItemSubclassQuest
{
    ITEM_SUBCLASS_QUEST = 0, ITEM_SUBCLASS_QUEST_2 = 1, ITEM_SUBCLASS_QUEST_3 = 3, ITEM_SUBCLASS_QUEST_8 = 8
};

#define MAX_ITEM_SUBCLASS_QUEST                   9

enum ItemSubclassKey
{
    ITEM_SUBCLASS_KEY = 0, ITEM_SUBCLASS_LOCKPICK = 1
};

#define MAX_ITEM_SUBCLASS_KEY                     2

enum ItemSubclassPermanent
{
    ITEM_SUBCLASS_PERMANENT = 0
};

#define MAX_ITEM_SUBCLASS_PERMANENT               1

enum ItemSubclassJunk
{
    ITEM_SUBCLASS_JUNK = 0, ITEM_SUBCLASS_JUNK_REAGENT = 1, ITEM_SUBCLASS_JUNK_PET = 2, ITEM_SUBCLASS_JUNK_HOLIDAY = 3, ITEM_SUBCLASS_JUNK_OTHER = 4, ITEM_SUBCLASS_JUNK_MOUNT = 5, ITEM_SUBCLASS_JUNK_OTHER_2 = 12
//1 item.
};

#define MAX_ITEM_SUBCLASS_JUNK                    13

enum ItemSubclassGlyph
{
    ITEM_SUBCLASS_GLYPH_WARRIOR = 1, ITEM_SUBCLASS_GLYPH_PALADIN = 2, ITEM_SUBCLASS_GLYPH_HUNTER = 3, ITEM_SUBCLASS_GLYPH_ROGUE = 4, ITEM_SUBCLASS_GLYPH_PRIEST = 5, ITEM_SUBCLASS_GLYPH_DEATH_KNIGHT = 6, ITEM_SUBCLASS_GLYPH_SHAMAN = 7, ITEM_SUBCLASS_GLYPH_MAGE = 8, ITEM_SUBCLASS_GLYPH_WARLOCK = 9, ITEM_SUBCLASS_GLYPH_DRUID = 11
};

#define MAX_ITEM_SUBCLASS_GLYPH                   12

const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] =
{ MAX_ITEM_SUBCLASS_CONSUMABLE, MAX_ITEM_SUBCLASS_CONTAINER, MAX_ITEM_SUBCLASS_WEAPON, MAX_ITEM_SUBCLASS_GEM, MAX_ITEM_SUBCLASS_ARMOR, MAX_ITEM_SUBCLASS_REAGENT, MAX_ITEM_SUBCLASS_PROJECTILE, MAX_ITEM_SUBCLASS_TRADE_GOODS, MAX_ITEM_SUBCLASS_GENERIC, MAX_ITEM_SUBCLASS_RECIPE, MAX_ITEM_SUBCLASS_MONEY, MAX_ITEM_SUBCLASS_QUIVER, MAX_ITEM_SUBCLASS_QUEST, MAX_ITEM_SUBCLASS_KEY, MAX_ITEM_SUBCLASS_PERMANENT, MAX_ITEM_SUBCLASS_JUNK, MAX_ITEM_SUBCLASS_GLYPH };

inline uint8 ItemSubClassToDurabilityMultiplierId (uint32 ItemClass, uint32 ItemSubClass)
{
    switch (ItemClass)
    {
    case ITEM_CLASS_WEAPON:
        return ItemSubClass;
    case ITEM_CLASS_ARMOR:
        return ItemSubClass + 21;
    }
    return 0;
}

// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform
#if defined(__GNUC__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif

struct _Damage
{
    float DamageMin;
    float DamageMax;
    uint32 DamageType;          // id from Resistances.dbc
};

struct _ItemStat
{
    uint32 ItemStatType;
    int32 ItemStatValue;
};
struct _Spell
{
    int32 SpellId;          // id from Spell.dbc
    uint32 SpellTrigger;
    int32 SpellCharges;
    float SpellPPMRate;
    int32 SpellCooldown;
    uint32 SpellCategory;          // id from SpellCategory.dbc
    int32 SpellCategoryCooldown;
};

struct _Socket
{
    uint32 Color;
    uint32 Content;
};

#define MAX_ITEM_PROTO_DAMAGES 2
#define MAX_ITEM_PROTO_SOCKETS 3
#define MAX_ITEM_PROTO_SPELLS  5
#define MAX_ITEM_PROTO_STATS  10

struct ItemPrototype
{
    uint32 ItemId;
    uint32 Class;          // id from ItemClass.dbc
    uint32 SubClass;          // id from ItemSubClass.dbc
    int32 Unk0;
    char* Name1;
    uint32 DisplayInfoID;          // id from ItemDisplayInfo.dbc
    uint32 Quality;
    uint32 Flags;
    uint32 Flags2;
    uint32 BuyCount;
    int32 BuyPrice;
    uint32 SellPrice;
    uint32 InventoryType;
    uint32 AllowableClass;
    uint32 AllowableRace;
    uint32 ItemLevel;
    uint32 RequiredLevel;
    uint32 RequiredSkill;          // id from SkillLine.dbc
    uint32 RequiredSkillRank;
    uint32 RequiredSpell;          // id from Spell.dbc
    uint32 RequiredHonorRank;
    uint32 RequiredCityRank;
    uint32 RequiredReputationFaction;          // id from Faction.dbc
    uint32 RequiredReputationRank;
    int32 MaxCount;          // <= 0: no limit
    int32 Stackable;          // 0: not allowed, -1: put in player coin info tab and don't limit stacking (so 1 slot)
    uint32 ContainerSlots;
    _ItemStat ItemStat[MAX_ITEM_PROTO_STATS];
    uint32 ScalingStatDistribution;          // id from ScalingStatDistribution.dbc
    uint32 ScalingStatValue;          // mask for selecting column in ScalingStatValues.dbc
    uint32 damageType;
    uint32 Delay;
    float RangedModRange;
    _Spell Spells[MAX_ITEM_PROTO_SPELLS];
    uint32 Bonding;
    char* Description;
    uint32 PageText;
    uint32 LanguageID;
    uint32 PageMaterial;
    uint32 StartQuest;          // id from QuestCache.wdb
    uint32 LockID;
    int32 Material;          // id from Material.dbc
    uint32 Sheath;
    int32 RandomProperty;          // id from ItemRandomProperties.dbc
    int32 RandomSuffix;          // id from ItemRandomSuffix.dbc
    uint32 Block;
    uint32 ItemSet;          // id from ItemSet.dbc
    uint32 MaxDurability;
    uint32 Area;          // id from AreaTable.dbc
    uint32 Map;          // id from Map.dbc
    uint32 BagFamily;          // bit mask (1 << id from ItemBagFamily.dbc)
    uint32 TotemCategory;          // id from TotemCategory.dbc
    _Socket Socket[MAX_ITEM_PROTO_SOCKETS];
    uint32 socketBonus;          // id from SpellItemEnchantment.dbc
    uint32 GemProperties;          // id from GemProperties.dbc
    int32 RequiredDisenchantSkill;
    float ArmorDamageModifier;
    int32 Duration;          // negative = realtime, positive = ingame time
    uint32 ItemLimitCategory;          // id from ItemLimitCategory.dbc
    uint32 HolidayId;          // id from Holidays.dbc
    uint32 ScriptId;
    uint32 DisenchantID;
    uint32 FoodType;
    uint32 MinMoneyLoot;
    uint32 MaxMoneyLoot;

    // helpers
    bool CanChangeEquipStateInCombat () const
    {
        switch (InventoryType)
        {
        case INVTYPE_RELIC:
        case INVTYPE_SHIELD:
        case INVTYPE_HOLDABLE:
            return true;
        }

        switch (Class)
        {
        case ITEM_CLASS_WEAPON:
        case ITEM_CLASS_PROJECTILE:
            return true;
        }

        return false;
    }

    uint32 GetMaxStackSize () const
    {
        return (Stackable == 2147483647 || Stackable <= 0) ? uint32(0x7FFFFFFF - 1) : uint32(Stackable);
    }

    int32 getFeralBonus (int32 extraDPS = 0) const
    {
        // 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
        if (Class == ITEM_CLASS_WEAPON && (1 << SubClass) & 0x02A5F3)
        {
            int32 bonus = int32((extraDPS + getDPS()) * 14.0f) - 767;
            if (bonus < 0)
                return 0;
            return bonus;
        }
        return 0;
    }

    float GetItemLevelIncludingQuality () const
    {
        float itemLevel = (float) ItemLevel;
        switch (Quality)
        {
        case ITEM_QUALITY_POOR:
        case ITEM_QUALITY_NORMAL:
        case ITEM_QUALITY_UNCOMMON:
        case ITEM_QUALITY_ARTIFACT:
        case ITEM_QUALITY_HEIRLOOM:
            itemLevel -= 13;          // leaving this as a separate statement since we do not know the real behavior in this case
            break;
        case ITEM_QUALITY_RARE:
            itemLevel -= 13;
            break;
        case ITEM_QUALITY_EPIC:
        case ITEM_QUALITY_LEGENDARY:
        default:
            break;
        }
        return itemLevel;
    }

    uint32 GetArmor () const;

    ItemDamageEntry const* getItemDamageEntry () const;
    float getDPS () const;
    float GetMinDamage () const
    {
        return floor(getDPS() * float(Delay) / 1000.0f * 0.7f + 0.5f);
    }
    float GetMaxDamage () const
    {
        return floor(getDPS() * float(Delay) / 1000.0f * 1.3f + 0.5f);
    }

    bool IsPotion () const
    {
        return Class == ITEM_CLASS_CONSUMABLE && SubClass == ITEM_SUBCLASS_POTION;
    }
    bool IsWeaponVellum () const
    {
        return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_WEAPON_ENCHANTMENT;
    }
    bool IsArmorVellum () const
    {
        return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ARMOR_ENCHANTMENT;
    }
    bool IsConjuredConsumable () const
    {
        return Class == ITEM_CLASS_CONSUMABLE && (Flags & ITEM_PROTO_FLAG_CONJURED);
    }
};

// Benchmarked: Faster than std::map (insert/find)
typedef UNORDERED_MAP<uint32, ItemPrototype > ItemTemplateContainer;

struct ItemLocale
{
    StringVector Name;
    StringVector Description;
};

struct ItemSetNameEntry
{
    std::string name;
    uint32 InventoryType;
};

struct ItemSetNameLocale
{
    StringVector Name;
};

// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
#endif
